Skip to content

Conversation

@AntonZarytski
Copy link

No description provided.

super.onCreate()
appComponent = DaggerAppComponent.builder().appModule(AppModule(this)).build()
activityComponent = DaggerActivityComponent.factory().create(appComponent)
fragmentReceverComponent = DaggerFragmentReceiverComponent.factory().create(activityComponent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем тебе эти компоненты на уровне апликейшена? это чревато утечками памяти, тк в этих комопнентах лежит ссылка на фрагменты. Создавай их прямо в активити/фрагментах

}

@Module
class FragmentReceiverModule(var context: Context) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не используй конструктор модуля, это bad practice тк ты не можешь использовать статические Provides методы и модуль теперь содержит стейт.

@FragmentScope
@Component(dependencies = [ActivityComponent::class], modules = [FragmentReceiverModule::class])
interface FragmentReceiverComponent {
var context: Context
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем эта проперти? Выглядит как какая-то смесь между сабкомпонентами и компонент депенденсис. Если ты выбрал сабкомпоненты то эти провижен методы/проперти не нужны

@Component(dependencies = [ActivityComponent::class], modules = [FragmentReceiverModule::class])
interface FragmentReceiverComponent {
var context: Context
var vmReceiver: ViewModelReceiver
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

И эта


@Component.Factory
interface Factory {
fun create(activityComponent: ActivityComponent): FragmentProducerComponent
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем ему в аргументах ActivityComponent если у тебя FragmentProducerComponent должен быть сабкомпонентом у ActivityComponent? в ActivityComponent должен появится провижен метод который отдает FragmentProducerComponent.Factory


@Module
class ActivityModule {
@get:Provides
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Этот модуль можно убрать. Добавь инжект аннотацию над ColorFlow

@Module
class ActivityModule {
@get:Provides
@ActivityScope
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Скоуп здесь не нужен

interface ActivityComponent {
var context: Context

fun injectInto(producer: FragmentProducer)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Зачем эти методы? Если у тебя компонент на активити то писать мембер инжектор методы на фрагмент это бед практис. Если тебе во фрагменте нужна какая то сущность, которая предоставляется ActivityComponent и его модулями, то для этого как раз и используются сабкомпоненты app -> activity -> fragment

private val context: Context
) {
) : ViewModel() {
@Inject
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему здесь инжект в поле? Инжекти в конструктор и ВМ создавай через фабрику, это предпочтительный способ, к тому же я не совсем понял как у тебя вообще код компилируется если здесь нет мембер инжектора

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
App.appComponent.injectInto(this)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Опять же, если у тебя компонент создается в Application и по смыслу и по названию относиться к Application, то его инжектить можно только в Application, если тебе нужны его сущности то выстраивай иерархию


@FragmentScope
@Binds
fun bindColorGenerator(colorGeneratorImpl: ColorGeneratorImpl): ColorGenerator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Смотри, у тебя ColorGeneratorImpl класс, который стейта не содержит, тоесть разницы между двумя экземплярами никакой не будет, в таком случае лучше делать unscoped зависимость, таким образом ты сэкономишь на synchronized блоке


@FragmentScope
@Binds
fun bindColorGenerator(colorGeneratorImpl: ColorGeneratorImpl): ColorGenerator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А почему у тебя ColorGenerator в двух модулях биндится? Если класс используется в 2 дочерних компонентах, мне кажется проще его в ActivityComponent положить?

import javax.inject.Scope

@FragmentScope
@Component(dependencies = [AppComponent::class, ActivityComponent::class], modules = [FragmentReceiverModule::class])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я думаю тебе правильнее сделать ActivityComponent зависимым от AppComponent, а оба компонента фрагментов зависимыми от ActivityComponent. Тогда у тебя получается понятная древовидная структура, в реальном приложении обычно так и происходит

@Module
interface FragmentReceiverModule {

@FragmentScope
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

То же самое про скоуп

}

@Qualifier
annotation class AppScope No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне кажется неправильно Qualifier аннотацию называть постфиксом Scope, это запутать может

class ViewModelReceiver(
private val context: Context
) {
class ViewModelReceiver @Inject constructor(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тебе здесь Inject аннотация не нужна, ты же через фабрики создаешь


fun activityContext(): Context

val observer: MutableLiveData<Int>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Правильнее делать именно методы


fun activityContext(): Context

val observer: MutableLiveData<Int>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тут есть проблема, у тебя сейчас в обоих фрагментах торчит MutableLiveData, то есть ты можешь заэмитить что-то в MutableLiveData даже из RecieverViewModel, который предполагается умеет только читать. Попробуй прокинуть туда экземпляр LiveData, а в ProducerViewModel прокинь MutableLiveData

import java.lang.RuntimeException
import javax.inject.Inject

class ViewModelProducer @Inject constructor (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Аннотация не нужна

import javax.inject.Inject

class ViewModelProducer @Inject constructor (
private val colorGenerator: ColorGenerator?,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему нуллабл?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants